#!/usr/bin/ruby
# -*- coding: utf-8 -*-
=begin
# QtClass.rb for  in /home/lund/Projets/ruby
# 
# Made by florian dewulf
# Login   <dewulf_f@epitech.net>
# 
# Started on  Thu Apr 25 23:58:30 2013 florian dewulf
# Last update Thu May  2 19:52:49 2013 florian dewulf
=end

require 'Qt'

load "Lexer.rb"

class   QtApp < Qt::Widget
#Slots Qt Define
  slots 'launch_script()'

#Constructor
  def   initialize
    super                                       #call the QtWidget Constructor
    setWindowTitle("Generateur de syscall")     #name the window
    init_ui                                     #call my creation window function
    setFixedSize(450, 200)                      #set the size of the window
    move(300, 300)                              #move the window
    show                                        #show the window
  end

  def   init_ui
    #creation and initialisation of my Widgets
    quit = Qt::Action.new("&Quit", self)
    label1 = Qt::Label.new('Bienvenue dans le générateur de tableau à Syscall', self)
    label1.setAlignment(Qt::AlignHCenter.to_i | Qt::AlignTop.to_i)
    label2 = Qt::Label.new('Emplacement du fichier unistd.h', self)
    @input_uni = Qt::LineEdit.new(self)
    @input_uni.setText("/usr/include/x86_64-linux-gnu/asm/unistd_64.h")
    label3 = Qt::Label.new('Emplacement du fichier syscalls.h', self)
    @input_sys = Qt::LineEdit.new(self)
    @input_sys.setText("/usr/src/linux-headers-3.5.0-27/include/linux/syscalls.h")
    label4 = Qt::Label.new('Emplacement du fichier de sauvegarde', self)
    @input_save = Qt::LineEdit.new(self)
    button_go = Qt::PushButton.new('Go !')
    button_quit = Qt::PushButton.new('Quit !')

    #Put all in a grid
    grid = Qt::GridLayout.new(self)
    grid.addWidget(label1, 0, 0, 1, 3)
    grid.addWidget(label2, 1, 0, 1, 1)
    grid.addWidget(@input_uni, 1, 1, 1, 2)
    grid.addWidget(label3, 2, 0, 1, 1)
    grid.addWidget(@input_sys, 2, 1, 1, 2)
    grid.addWidget(label4, 3, 0, 1, 1)
    grid.addWidget(@input_save, 3, 1, 1, 2)
    grid.add_widget(button_go, 4, 1, 1, 1)
    grid.add_widget(button_quit, 4, 2, 1, 1)

    #put the signal catch for the button
    connect(button_quit, SIGNAL('clicked()'), $qApp, SLOT('quit()'))
    connect(button_go, SIGNAL('clicked()'), self, SLOT("launch_script()"))
  end

  def   launch_script
    #take the text in the input fields
    txt_unistd = @input_uni.text
    txt_syscalls = @input_sys.text
    txt_save = @input_save.text

    #check if they are filled
    if (txt_unistd == "" || txt_syscalls == "" || txt_save == "")
      Qt::MessageBox.critical self, "Error", "Input empty !"
      return
    end

    #try to open the file, if it doesn't work, a warning pop up
    begin
      @file_uni = File.open(txt_unistd, "r")
    rescue
      Qt::MessageBox.critical self, "Error", "Cannot open the unistd file !"
      return
    end

    #try to open the file, if it doesn't work, a warning pop up
    begin
      @file_sys = File.open(txt_syscalls, "r")
    rescue
      Qt::MessageBox.critical self, "Error", "Cannot open the syscall file !"
      return
    end

    #try to open the file, if it doesn't work, try to create the file, if it doesn't again, a warning pop up
    begin
      @file_save = File.open(txt_save, "w+")
    rescue
      begin
        @file_save = File::new(txt_save, "w+")
      rescue
        Qt::MessageBox.critical self, "Error", "Cannot open the save file !"
        return
      end
    end

    #now with our files, we can call the script
    self.script
  end

  def   script
    #creation of the ProgressBar pop-up
    progressDialog = Qt::ProgressDialog.new(self)
    progressDialog.setValue(0)
    progressDialog.show

    #here the script
    lex = Lexer.new(@file_uni, @file_sys)
    hash_unistd = lex.hash_unistd(progressDialog)
    hash_syscall = lex.hash_syscall(progressDialog)

    #check the hash {id, syscall name} with the hash {syscall name, arguments} to create a hash {id, syscall name, arguments}
    hash_res = []
    hash_unistd.each { |x|
      hash_syscall.each { |y|
        if (y[:syscall] == x[:syscall])
          tmp = x
          tmp[:args] = y[:args]
          hash_res << tmp
        end
      }
    }

    #write the tab
    @file_save.write "#ifndef\t\tSYSCALL_H__\n# define\tSYSCALL_H__\n\n#include\t\t\"strace.h\"\n\n"
    @file_save.write "t_syscall tab_syscall[] = {\n"
    i = 0
    hash_res.each { |x|
      if (i != 0)
        @file_save.write ",\n"
      end
      if (x[:syscall] == "mmap" || x[:syscall] == "mremap" || x[:syscall] == "brk")
        @file_save.write "\t{#{x[:id]}, PTR, \"#{x[:syscall]}\", "
      else
        @file_save.write "\t{#{x[:id]}, INT, \"#{x[:syscall]}\", "
      end
        @file_save.write "{"
      if (x[:args] != "void")
        tab = x[:args].split(",")
        nb_arg = 0
        tab.each { |arg|
          if (arg.include?("struct") || arg.include?("void *") || (!arg.include?("char") && arg.include?("*")))
            @file_save.write "PTR, "
          elsif (arg.include?("*") && arg.include?("char"))
            @file_save.write "STRING, "
          else
            if (arg.include? "unsigned")
              @file_save.write "U_"
            end
            if ((arg.include?("unsigned") && !arg.include?("char") && !arg.include?("long")) ||
                (arg.include?("int")))
              @file_save.write "INT"
            elsif (arg.include? "char")
              @file_save.write "CHAR"
            elsif (arg.include? "long")
              @file_save.write "LONG"
            else
              @file_save.write "INT"
            end
            @file_save.write ", "
          end
          nb_arg += 1
        }
        while (nb_arg < 6)
          @file_save.write "VOID, "
          nb_arg += 1
        end
      else
        @file_save.write "VOID, VOID, VOID, VOID, VOID, VOID, "
      end
      i += 1
      @file_save.write "VOID}}"
    }
    @file_save.write "\n};\n\n#endif"

    #close the files, it's finished
    @file_uni.close
    @file_sys.close
    @file_save.close
  end

end

app = Qt::Application.new ARGV
QtApp.new
app.exec
